package sk.tuke.magsa.tools.parserxml;

import java.io.File;
import java.io.Reader;
import javax.xml.XMLConstants;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;
import javax.xml.validation.SchemaFactory;
import org.xml.sax.SAXException;
import sk.tuke.magsa.tools.metamodel.Entity;
import sk.tuke.magsa.tools.metamodel.Model;
import sk.tuke.magsa.tools.metamodel.Property;
import sk.tuke.magsa.tools.metamodel.ui.Component;
import sk.tuke.magsa.tools.metamodel.ui.Dialog;
import sk.tuke.magsa.tools.metamodel.ui.LookupColumn;
import sk.tuke.magsa.tools.metamodel.ui.LookupField;
import sk.tuke.magsa.tools.metamodel.ui.UI;

public class UIProcessor {
    private UI ui;

    private Model model;

    public UIProcessor(Reader xmlReader, File schemaFile) throws UIProcessingException {
        try {
            JAXBContext jc = JAXBContext.newInstance("sk.tuke.magsa.tools.metamodel.ui", this.getClass().getClassLoader());
            Unmarshaller unmarshaller = jc.createUnmarshaller();
            // Turn on validation
            unmarshaller.setSchema(SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI).newSchema(schemaFile));
            // Unmarshall
            ui = (UI) unmarshaller.unmarshal(xmlReader);
        } catch (SAXException e) {
            throw new UIProcessingException("Cannot process xml input", e);
        } catch (JAXBException e) {
            throw new UIProcessingException("Cannot process xml input", e);
        }
    }

    public UI getUi() {
        return ui;
    }

    public void compose(Model model) throws UIProcessingException {
        this.model = model;
        validate();
        model.setUi(ui);
    }

    private void validate() throws UIProcessingException {
        validate(ui.getTables());
        validate(ui.getForms());
    }

    private void validate(Dialog[] dialogs) throws UIProcessingException {
        for(Dialog dialog : dialogs)
        {
            Entity entity = model.findEntity(dialog.getEntityName());
            if(entity == null)
            {
                throw new UIProcessingException("Entity " + dialog.getEntityName() +" does not exist");
            }
            dialog.setEntity(entity);
            for(Component component : dialog.getComponents())
            {
                Property property;
                
                if(component instanceof LookupColumn)
                {
                    LookupColumn lColumn = (LookupColumn)component;
                    lColumn.setEntity(model.findEntity(lColumn.getEntityName()));
                    property = lColumn.getEntity().findProperty(component.getPropertyName());
                    
                    if(property == null)
                    {
                        throw new UIProcessingException("property " + component.getPropertyName() + " does not exist in referenced entity " + entity.getName());
                    }
                    else
                    {
                        lColumn.setProperty(property);
                    }
                }
                else if (component instanceof LookupField)
                {
                    LookupField lField = (LookupField)component;
                    lField.getTable().setEntity(model.findEntity(lField.getTable().getEntityName()));
                    property = lField.getTable().getEntity().findProperty(component.getPropertyName());
                    
                    if(property == null)
                    {
                        throw new UIProcessingException("property " + component.getPropertyName() + " does not exist in referenced entity " + entity.getName());
                    }
                    else
                    {
                        lField.setProperty(property);
                    }
                }
                else
                {
                    property = entity.findProperty(component.getPropertyName());
                    
                    if(property == null)
                    {
                        throw new UIProcessingException("property " + component.getPropertyName() + " does not exist in entity " + entity.getName());
                    }
                    else
                    {
                        component.setProperty(property);
                    }
                }
            }
        }
    }
    
//    private void validate(Dialog[] dialogs) throws UIProcessingException {
//        Entity e;
//        Entity refE;
//        Property p;
//        String entName;
//        for(Dialog d : dialogs){
//            if((e = model.findEntity(d.getEntityName())) == null){
//                throw new UIProcessingException("Wrong entity name: " + d.getEntityName());
//            } else{
//                d.setEntity(e);
//                for(Component c : d.getComponents()){
//                    if(c instanceof LookupColumn){
//                        entName = ((LookupColumn)c).getEntityName();
//                        if((refE = model.findEntity(entName)) == null){
//                            throw new UIProcessingException("Wrong referenced entity name: " + entName);
//                        }
//                        if((p=refE.findProperty(c.getPropertyName())) == null){
//                            throw new UIProcessingException("Wrong referenced property name: " + c.getPropertyName());
//                        }
//                        c.setProperty(p);
//                    } else if(c instanceof LookupField){
//                        entName = ((LookupField)c).getTable().getEntityName();
//                        if((refE = model.findEntity(entName)) == null){
//                            throw new UIProcessingException("Wrong referenced entity name: " + entName);
//                        }
//                        if((p=refE.findProperty(c.getPropertyName())) == null){
//                            throw new UIProcessingException("Wrong referenced property name: " + c.getPropertyName());
//                        }
//                        c.setProperty(p);
//                    } else {
//                        if((p=e.findProperty(c.getPropertyName())) == null){
//                            throw new UIProcessingException("Wrong property name: " + c.getPropertyName());
//                        }
//                        c.setProperty(p);
//                    }
//                }
//            }
//        }
//    }
}
